/*     */ package com.zimbra.cs.mailclient.auth;
/*     */ 
/*     */ import com.zimbra.common.util.Log;
/*     */ import com.zimbra.cs.mailclient.MailConfig;
/*     */ import com.zimbra.cs.security.sasl.SaslInputStream;
/*     */ import com.zimbra.cs.security.sasl.SaslOutputStream;
/*     */ import com.zimbra.cs.security.sasl.SaslSecurityLayer;
/*     */ import java.io.IOException;
/*     */ import java.io.InputStream;
/*     */ import java.io.OutputStream;
/*     */ import java.security.PrivilegedActionException;
/*     */ import java.security.PrivilegedExceptionAction;
/*     */ import java.util.HashMap;
/*     */ import java.util.Map;
/*     */ import javax.security.auth.Subject;
/*     */ import javax.security.auth.callback.Callback;
/*     */ import javax.security.auth.callback.CallbackHandler;
/*     */ import javax.security.auth.callback.NameCallback;
/*     */ import javax.security.auth.callback.PasswordCallback;
/*     */ import javax.security.auth.callback.UnsupportedCallbackException;
/*     */ import javax.security.auth.login.AppConfigurationEntry;
/*     */ import javax.security.auth.login.AppConfigurationEntry.LoginModuleControlFlag;
/*     */ import javax.security.auth.login.Configuration;
/*     */ import javax.security.auth.login.LoginContext;
/*     */ import javax.security.auth.login.LoginException;
/*     */ import javax.security.sasl.RealmCallback;
/*     */ import javax.security.sasl.Sasl;
/*     */ import javax.security.sasl.SaslClient;
/*     */ import javax.security.sasl.SaslException;
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ public final class SaslAuthenticator
/*     */   extends Authenticator
/*     */ {
/*     */   private MailConfig config;
/*     */   private String password;
/*     */   private LoginContext loginContext;
/*     */   private Subject subject;
/*     */   private SaslClient saslClient;
/*     */   public static final String GSSAPI = "GSSAPI";
/*     */   public static final String PLAIN = "PLAIN";
/*     */   public static final String CRAM_MD5 = "CRAM-MD5";
/*     */   public static final String DIGEST_MD5 = "DIGEST-MD5";
/*     */   public static final String QOP_AUTH = "auth";
/*     */   public static final String QOP_AUTH_CONF = "auth-conf";
/*     */   public static final String QOP_AUTH_INT = "auth-int";
/*     */   private static final String LOGIN_MODULE_NAME = "com.sun.security.auth.module.Krb5LoginModule";
/*     */   
/*     */   public void init(MailConfig config, String password)
/*     */     throws LoginException, SaslException
/*     */   {
/*  67 */     this.config = config;
/*  68 */     this.password = password;
/*  69 */     String mechanism = config.getMechanism();
/*  70 */     checkRequired("mechanism", mechanism);
/*  71 */     checkRequired("host", config.getHost());
/*  72 */     checkRequired("protocol", config.getProtocol());
/*  73 */     checkRequired("authentication id", config.getAuthenticationId());
/*  74 */     this.saslClient = (mechanism.equals("GSSAPI") ? createGssSaslClient() : createSaslClient());
/*  75 */     Map<String, String> props = config.getSaslProperties();
/*  76 */     String qop = "auth";
/*  77 */     if (props != null) {
/*  78 */       qop = (String)props.get("javax.security.sasl.qop");
/*     */     }
/*  80 */     debug("Requested QOP is %s", new Object[] { qop != null ? qop : "auth" });
/*     */   }
/*     */   
/*     */   public String getMechanism()
/*     */   {
/*  85 */     return this.config.getMechanism();
/*     */   }
/*     */   
/*     */   private static void checkRequired(String name, String value) {
/*  89 */     if (value == null) {
/*  90 */       throw new IllegalArgumentException("Missing required " + name);
/*     */     }
/*     */   }
/*     */   
/*     */   private SaslClient createGssSaslClient() throws LoginException, SaslException {
/*  95 */     this.loginContext = getLoginContext();
/*  96 */     this.loginContext.login();
/*  97 */     this.subject = this.loginContext.getSubject();
/*  98 */     debug("GSS subject = %s", new Object[] { this.subject });
/*     */     try {
/* 100 */       (SaslClient)Subject.doAs(this.subject, new PrivilegedExceptionAction()
/*     */       {
/*     */         public SaslClient run() throws SaslException {
/* 103 */           return SaslAuthenticator.this.createSaslClient();
/*     */         }
/*     */       });
/*     */     } catch (PrivilegedActionException e) {
/* 107 */       dispose();
/* 108 */       Exception cause = e.getException();
/* 109 */       if ((cause instanceof SaslException))
/* 110 */         throw ((SaslException)cause);
/* 111 */       if ((cause instanceof LoginException)) {
/* 112 */         throw ((LoginException)cause);
/*     */       }
/* 114 */       throw new IllegalStateException("Error initialization GSS authenticator", e);
/*     */     }
/*     */   }
/*     */   
/*     */ 
/*     */   private LoginContext getLoginContext()
/*     */     throws LoginException
/*     */   {
/* 122 */     Map<String, String> options = new HashMap();
/* 123 */     options.put("debug", Boolean.toString(this.config.getLogger().isDebugEnabled()));
/* 124 */     options.put("principal", getPrincipal());
/*     */     
/*     */ 
/* 127 */     final AppConfigurationEntry ace = new AppConfigurationEntry("com.sun.security.auth.module.Krb5LoginModule", AppConfigurationEntry.LoginModuleControlFlag.REQUIRED, options);
/*     */     
/* 129 */     Configuration config = new Configuration()
/*     */     {
/*     */       public AppConfigurationEntry[] getAppConfigurationEntry(String name) {
/* 132 */         return new AppConfigurationEntry[] { ace };
/*     */       }
/*     */       
/*     */ 
/*     */       public void refresh() {}
/* 137 */     };
/* 138 */     return new LoginContext("krb5", null, new SaslCallbackHandler(null), config);
/*     */   }
/*     */   
/*     */   private String getPrincipal() {
/* 142 */     String realm = this.config.getRealm();
/* 143 */     String authenticationId = this.config.getAuthenticationId();
/* 144 */     return (realm != null) && (authenticationId.indexOf('@') == -1) ? authenticationId + '@' + realm : authenticationId;
/*     */   }
/*     */   
/*     */   private SaslClient createSaslClient() throws SaslException {
/* 148 */     return Sasl.createSaslClient(new String[] { this.config.getMechanism() }, this.config.getAuthorizationId(), this.config.getProtocol(), this.config.getHost(), this.config.getSaslProperties(), new SaslCallbackHandler(null));
/*     */   }
/*     */   
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */   public byte[] evaluateChallenge(byte[] challenge)
/*     */     throws SaslException
/*     */   {
/* 159 */     if (isComplete()) {
/* 160 */       throw new IllegalStateException("Authentication already completed");
/*     */     }
/* 162 */     return this.subject != null ? evaluateGssChallenge(challenge) : this.saslClient.evaluateChallenge(challenge);
/*     */   }
/*     */   
/*     */   private byte[] evaluateGssChallenge(final byte[] challenge) throws SaslException
/*     */   {
/*     */     try {
/* 168 */       (byte[])Subject.doAs(this.subject, new PrivilegedExceptionAction()
/*     */       {
/*     */         public byte[] run() throws SaslException {
/* 171 */           return SaslAuthenticator.this.saslClient.evaluateChallenge(challenge);
/*     */         }
/*     */       });
/*     */     } catch (PrivilegedActionException e) {
/* 175 */       dispose();
/* 176 */       Throwable cause = e.getCause();
/* 177 */       if ((cause instanceof SaslException)) {
/* 178 */         throw ((SaslException)cause);
/*     */       }
/* 180 */       throw new IllegalStateException("Unknown authentication error", cause);
/*     */     }
/*     */   }
/*     */   
/*     */   public byte[] getInitialResponse()
/*     */     throws SaslException
/*     */   {
/* 187 */     if (!hasInitialResponse()) {
/* 188 */       throw new IllegalStateException("Mechanism does not support initial response");
/*     */     }
/* 190 */     return this.saslClient.evaluateChallenge(new byte[0]);
/*     */   }
/*     */   
/*     */   public boolean hasInitialResponse()
/*     */   {
/* 195 */     return this.saslClient.hasInitialResponse();
/*     */   }
/*     */   
/*     */ 
/*     */ 
/* 200 */   public boolean isComplete() { return this.saslClient.isComplete(); }
/*     */   
/*     */   private class SaslCallbackHandler implements CallbackHandler {
/*     */     private SaslCallbackHandler() {}
/*     */     
/*     */     public void handle(Callback[] cbs) throws IOException, UnsupportedCallbackException {
/* 206 */       for (Callback cb : cbs) {
/* 207 */         if ((cb instanceof NameCallback)) {
/* 208 */           ((NameCallback)cb).setName(SaslAuthenticator.this.config.getAuthenticationId());
/* 209 */         } else if ((cb instanceof PasswordCallback)) {
/* 210 */           if (SaslAuthenticator.this.password == null) {
/* 211 */             throw new IllegalStateException("Password missing but required");
/*     */           }
/* 213 */           ((PasswordCallback)cb).setPassword(SaslAuthenticator.this.password.toCharArray());
/* 214 */           SaslAuthenticator.this.password = null;
/* 215 */         } else if ((cb instanceof RealmCallback)) {
/* 216 */           String realm = SaslAuthenticator.this.config.getRealm();
/* 217 */           if (realm == null) {
/* 218 */             throw new IllegalStateException("Realm missing but required");
/*     */           }
/* 220 */           ((RealmCallback)cb).setText(realm);
/*     */         } else {
/* 222 */           throw new UnsupportedCallbackException(cb);
/*     */         }
/*     */       }
/*     */     }
/*     */   }
/*     */   
/*     */   public boolean isEncryptionEnabled()
/*     */   {
/* 230 */     return SaslSecurityLayer.getInstance(this.saslClient).isEnabled();
/*     */   }
/*     */   
/*     */   public OutputStream wrap(OutputStream os)
/*     */   {
/* 235 */     return isEncryptionEnabled() ? new SaslOutputStream(os, this.saslClient) : os;
/*     */   }
/*     */   
/*     */   public InputStream unwrap(InputStream is)
/*     */   {
/* 240 */     return isEncryptionEnabled() ? new SaslInputStream(is, this.saslClient) : is;
/*     */   }
/*     */   
/*     */   public String getNegotiatedProperty(String name)
/*     */   {
/* 245 */     return (String)this.saslClient.getNegotiatedProperty(name);
/*     */   }
/*     */   
/*     */   public void dispose() throws SaslException
/*     */   {
/* 250 */     this.saslClient.dispose();
/* 251 */     if (this.loginContext != null) {
/*     */       try {
/* 253 */         this.loginContext.logout();
/*     */       } catch (LoginException e) {
/* 255 */         e.printStackTrace();
/*     */       }
/* 257 */       this.loginContext = null;
/*     */     }
/*     */   }
/*     */   
/*     */   private void debug(String format, Object... args) {
/* 262 */     if (this.config.getLogger().isDebugEnabled()) {
/* 263 */       this.config.getLogger().debug("[SaslAuthenticator] " + format + "\n", args);
/*     */     }
/*     */   }
/*     */ }


/* Location:              /home/mint/zimbrastore.jar!/com/zimbra/cs/mailclient/auth/SaslAuthenticator.class
 * Java compiler version: 7 (51.0)
 * JD-Core Version:       0.7.1
 */